#include <iostream>
#include "structures.h"
#include "io.h"

using namespace std;

/**
 * Reads settings from standand input stream and returns them
 */
game_settings read_settings()
{
	game_settings settings;
	int player_num;

	cin >> settings.field_radius >> settings.move_interval >> settings.fsp >> settings.nsp;
	cin >> player_num;

	if (player_num == 1)
	{
		settings.my_num = 1;
		settings.enemy_num = 2;
	}
	else
	{
		settings.my_num = 2;
		settings.enemy_num = 1;
	}

	return settings;
}

/**
 * Reads unit types from standand input stream and returns them
 */
vector<unit_type> read_unit_types()
{
	vector<unit_type> unit_types;
	int count;

	cin >> count;
	for(int i = 0; i < count; i++)
	{
		unit_type type;
		cin >> type.max_health >> type.shot_damage >> type.move_radius >> type.shot_radius;
		unit_types.push_back(type);
	}

	return unit_types;
}

/**
 * Reads zones for unit location from standand input stream and returns them
 */
vector<zone> read_zones(int board_radius)
{
	vector<zone> zones;
	int zone_count;

	cin >> zone_count;

	for(int i = 0; i < zone_count; i++)
	{
		zone z;
		cin >> z.x >> z.y >> z.player_num;
		z.x += board_radius;
		z.y += board_radius;
		zones.push_back(z);
	}

	return zones;
}

/**
 * Reads unit groups, available for location the map, from standand input
 * stream and returns them
 */
vector<available> read_available_units()
{
	vector<available> groups;
	int count;

	cin >> count;
	for (int i = 0; i < count; i++)
	{
		available group;
		cin >> group.unit_type_id >> group.unit_count;
		if (group.unit_count != 0)
		{
			groups.push_back(group);
		}
	}

	return groups;
}

/**
 * Writes unit locations to standand output stream
 */
void write_locations(const vector<location>& locations, int board_radius)
{
	cout << locations.size() << endl;
	for (unsigned i = 0; i < locations.size(); i++)
	{
		cout << (locations[i].x - board_radius) << ' ' << (locations[i].y - board_radius) << ' ';
		cout << locations[i].unit_type_id << ' ' << locations[i].unit_count << endl;
	}
}

/**
 * Reads game situation from standand input and updates states and field
 * arguments with it
 */
void read_situation(vector<state>& states, game_field& field, int board_radius)
{
	int count;

	cin >> count;
	states.resize(count);

	field.resize(2 * board_radius + 1);
	for (unsigned i = 0; i < field.size(); i++)
	{
		field[i].resize(2 * board_radius + 1);
	}

	for (unsigned i = 0; i < field.size(); i++)
	{
		for (unsigned j = 0; j < field.size(); j++)
		{
			field[i][j].player_num = 0;
		}
	}

	for (int i = 0; i < count; i++)
	{
		state group;
		cin >> group.x >> group.y >> group.player_num >> group.unit_type_id;
		cin >> group.unit_count >> group.last_unit_health >> group.since_last_move;
		group.x += board_radius;
		group.y += board_radius;
		states[i] = group;
		field[group.x][group.y] = group;
	}
}

/**
 * Reads move from standand input and returns it
 */
move read_move(int field_radius)
{
	move m;
	cin >> m.unit_count;
	cin >> m.from_x >> m.from_y;
	cin >> m.to_x >> m.to_y;
	cin >> m.attack_x >> m.attack_y;
	m.from_x += field_radius;
	m.from_y += field_radius;
	m.to_x += field_radius;
	m.to_y += field_radius;
	m.attack_x += field_radius;
	m.attack_y += field_radius;
	return m;
}

/**
 * Writes move to standand input
 */
void write_move(move m, int field_radius)
{
	if (m.unit_count != 0)
	{
		m.from_x -= field_radius;
		m.from_y -= field_radius;
		m.to_x -= field_radius;
		m.to_y -= field_radius;
		m.attack_x -= field_radius;
		m.attack_y -= field_radius;
	}

	cout << m.unit_count << ' ';
	cout << m.from_x << ' ' << m.from_y << ' ';
	cout << m.to_x << ' ' << m.to_y << ' ';
	cout << m.attack_x << ' ' << m.attack_y << endl;
}